<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Retina and real-world vision</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d3/d81/tutorial_contrib_root.html">Tutorials for contrib modules</a></li><li class="navelem"><a class="el" href="../../df/dee/tutorial_table_of_content_retina.html">Discovering the human retina and its use for image processing</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Retina and real-world vision </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h2>Goal </h2>
<p>I present here a model of human retina that shows some interesting properties for image preprocessing and enhancement. In this tutorial you will learn how to:</p>
<ul>
<li>discover the main two channels outing from your retina</li>
<li>see the basics to use the retina model</li>
<li>discover some parameters tweaks</li>
</ul>
<h2>General overview </h2>
<p>The proposed model originates from Jeanny Herault's research <a class="el" href="../../d0/de3/citelist.html#CITEREF_Herault2010">[121]</a> at <a href="http://www.gipsa-lab.inpg.fr">Gipsa</a>. It is involved in image processing applications with <a href="http://www.listic.univ-savoie.fr">Listic</a> (code maintainer and user) lab. This is not a complete model but it already present interesting properties that can be involved for enhanced image processing experience. The model allows the following human retina properties to be used :</p>
<ul>
<li>spectral whitening that has 3 important effects: high spatio-temporal frequency signals canceling (noise), mid-frequencies details enhancement and low frequencies luminance energy reduction. This <em>all in one</em> property directly allows visual signals cleaning of classical undesired distortions introduced by image sensors and input luminance range.</li>
<li>local logarithmic luminance compression allows details to be enhanced even in low light conditions.</li>
<li>decorrelation of the details information (Parvocellular output channel) and transient information (events, motion made available at the Magnocellular output channel).</li>
</ul>
<p>The first two points are illustrated below :</p>
<p>In the figure below, the OpenEXR image sample <em>CrissyField.exr</em>, a High Dynamic Range image is shown. In order to make it visible on this web-page, the original input image is linearly rescaled to the classical image luminance range [0-255] and is converted to 8bit/channel format. Such strong conversion hides many details because of too strong local contrasts. Furthermore, noise energy is also strong and pollutes visual information.</p>
<div class="image">
<img src="../../retina_TreeHdr_small.jpg" alt="retina_TreeHdr_small.jpg"/>
<div class="caption">
image</div></div>
<p> In the following image, applying the ideas proposed in <a class="el" href="../../d0/de3/citelist.html#CITEREF_Benoit2010">[19]</a>, as your retina does, local luminance adaptation, spatial noise removal and spectral whitening work together and transmit accurate information on lower range 8bit data channels. On this picture, noise in significantly removed, local details hidden by strong luminance contrasts are enhanced. Output image keeps its naturalness and visual content is enhanced. Color processing is based on the color multiplexing/demultiplexing method proposed in <a class="el" href="../../d0/de3/citelist.html#CITEREF_Chaix2007">[54]</a> .</p>
<div class="image">
<img src="../../retina_TreeHdr_retina.jpg" alt="retina_TreeHdr_retina.jpg"/>
<div class="caption">
image</div></div>
<p> <em>Note :</em> image sample can be downloaded from the <a href="http://www.openexr.com">OpenEXR website</a>. Regarding this demonstration, before retina processing, input image has been linearly rescaled within 0-255 keeping its channels float format. 5% of its histogram ends has been cut (mostly removes wrong HDR pixels). Check out the sample <em>opencv/samples/cpp/OpenEXRimages_HighDynamicRange_Retina_toneMapping.cpp</em> for similar processing. The following demonstration will only consider classical 8bit/channel images.</p>
<h2>The retina model output channels </h2>
<p>The retina model presents two outputs that benefit from the above cited behaviors.</p>
<ul>
<li>The first one is called the Parvocellular channel. It is mainly active in the foveal retina area (high resolution central vision with color sensitive photo-receptors), its aim is to provide accurate color vision for visual details remaining static on the retina. On the other hand objects moving on the retina projection are blurred.</li>
<li>The second well known channel is the Magnocellular channel. It is mainly active in the retina peripheral vision and send signals related to change events (motion, transient events, etc.). These outing signals also help visual system to focus/center retina on 'transient'/moving areas for more detailed analysis thus improving visual scene context and object classification.</li>
</ul>
<p><b>NOTE :</b> regarding the proposed model, contrary to the real retina, we apply these two channels on the entire input images using the same resolution. This allows enhanced visual details and motion information to be extracted on all the considered images... but remember, that these two channels are complementary. For example, if Magnocellular channel gives strong energy in an area, then, the Parvocellular channel is certainly blurred there since there is a transient event.</p>
<p>As an illustration, we apply in the following the retina model on a webcam video stream of a dark visual scene. In this visual scene, captured in an amphitheater of the university, some students are moving while talking to the teacher.</p>
<p>In this video sequence, because of the dark ambiance, signal to noise ratio is low and color artifacts are present on visual features edges because of the low quality image capture tool-chain.</p>
<div class="image">
<img src="../../studentsSample_input.jpg" alt="studentsSample_input.jpg"/>
<div class="caption">
image</div></div>
<p> Below is shown the retina foveal vision applied on the entire image. In the used retina configuration, global luminance is preserved and local contrasts are enhanced. Also, signal to noise ratio is improved : since high frequency spatio-temporal noise is reduced, enhanced details are not corrupted by any enhanced noise.</p>
<div class="image">
<img src="../../studentsSample_parvo.jpg" alt="studentsSample_parvo.jpg"/>
<div class="caption">
image</div></div>
<p> Below is the output of the Magnocellular output of the retina model. Its signals are strong where transient events occur. Here, a student is moving at the bottom of the image thus generating high energy. The remaining of the image is static however, it is corrupted by a strong noise. Here, the retina filters out most of the noise thus generating low false motion area 'alarms'. This channel can be used as a transient/moving areas detector : it would provide relevant information for a low cost segmentation tool that would highlight areas in which an event is occurring.</p>
<div class="image">
<img src="../../studentsSample_magno.jpg" alt="studentsSample_magno.jpg"/>
<div class="caption">
image</div></div>
 <h2>Retina use case </h2>
<p>This model can be used basically for spatio-temporal video effects but also in the aim of :</p>
<ul>
<li>performing texture analysis with enhanced signal to noise ratio and enhanced details robust against input images luminance ranges (check out the Parvocellular retina channel output)</li>
<li>performing motion analysis also taking benefit of the previously cited properties.</li>
</ul>
<h2>Literature </h2>
<p>For more information, refer to the following papers : <a class="el" href="../../d0/de3/citelist.html#CITEREF_Benoit2010">[19]</a></p>
<ul>
<li>Please have a look at the reference work of Jeanny Herault that you can read in his book <a class="el" href="../../d0/de3/citelist.html#CITEREF_Herault2010">[121]</a></li>
</ul>
<p>This retina filter code includes the research contributions of phd/research colleagues from which code has been redrawn by the author :</p>
<ul>
<li>take a look at the <em>retinacolor.hpp</em> module to discover Brice Chaix de Lavarene phD color mosaicing/demosaicing and his reference paper <a class="el" href="../../d0/de3/citelist.html#CITEREF_Chaix2007">[54]</a></li>
<li>take a look at <em>imagelogpolprojection.hpp</em> to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. More informations in the above cited Jeanny Heraults's book.</li>
</ul>
<h2>Code tutorial </h2>
<p>Please refer to the original tutorial source code in file <em>opencv_folder/samples/cpp/tutorial_code/bioinspired/retina_tutorial.cpp</em>.</p>
<dl class="section note"><dt>Note</dt><dd>do not forget that the retina model is included in the following namespace: <a class="el" href="../../d2/d81/namespacecv_1_1bioinspired.html">cv::bioinspired</a></dd></dl>
<p>To compile it, assuming OpenCV is correctly installed, use the following command. It requires the opencv_core *(<a class="el" href="../../d3/d63/classcv_1_1Mat.html" title="n-dimensional dense array class ">cv::Mat</a> and friends objects management)*, opencv_highgui *(display and image/video read)* and opencv_bioinspired *(Retina description)* libraries to compile.</p>
<div class="fragment"><div class="line">// compile</div><div class="line">gcc retina_tutorial.cpp -o Retina_tuto -lopencv_core -lopencv_highgui -lopencv_bioinspired -lopencv_videoio -lopencv_imgcodecs</div><div class="line"></div><div class="line">// Run commands : add &#39;log&#39; as a last parameter to apply a spatial log sampling (simulates retina sampling)</div><div class="line">// run on webcam</div><div class="line">./Retina_tuto -video</div><div class="line">// run on video file</div><div class="line">./Retina_tuto -video myVideo.avi</div><div class="line">// run on an image</div><div class="line">./Retina_tuto -image myPicture.jpg</div><div class="line">// run on an image with log sampling</div><div class="line">./Retina_tuto -image myPicture.jpg log</div></div><!-- fragment --><p>Here is a code explanation :</p>
<p>Retina definition is present in the bioinspired package and a simple include allows to use it. You can rather use the specific header : <em><a class="el" href="../../d2/dfa/bioinspired_8hpp.html">opencv2/bioinspired.hpp</a></em> if you prefer but then include the other required openv modules : <em><a class="el" href="../../d0/d9c/core_2include_2opencv2_2core_8hpp.html">opencv2/core.hpp</a></em> and <em><a class="el" href="../../d4/dd5/highgui_8hpp.html">opencv2/highgui.hpp</a></em> </p><div class="fragment"><div class="line"><span class="preprocessor">#include &quot;opencv2/opencv.hpp&quot;</span></div></div><!-- fragment --><p> Provide user some hints to run the program with a help function </p><div class="fragment"><div class="line"><span class="comment">// the help procedure</span></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> help(std::string errorMessage)</div><div class="line">{</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;Program init error : &quot;</span>&lt;&lt;errorMessage&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;\nProgram call procedure : retinaDemo [processing mode] [Optional : media target] [Optional LAST parameter: \&quot;log\&quot; to activate retina log sampling]&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;\t[processing mode] :&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;\t -image : for still image processing&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;\t -video : for video stream processing&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;\t[Optional : media target] :&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;\t if processing an image or video file, then, specify the path and filename of the target to process&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;\t leave empty if processing video stream coming from a connected video device&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;\t[Optional : activate retina log sampling] : an optional last parameter can be specified for retina spatial log sampling&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;\t set \&quot;log\&quot; without quotes to activate this sampling, output frame size will be divided by 4&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;\nExamples:&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;\t-Image processing : ./retinaDemo -image lena.jpg&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;\t-Image processing with log sampling : ./retinaDemo -image lena.jpg log&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;\t-Video processing : ./retinaDemo -video myMovie.mp4&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;\t-Live video processing : ./retinaDemo -video&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;\nPlease start again with new parameters&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot;****************************************************&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot; NOTE : this program generates the default retina parameters file &#39;RetinaDefaultParameters.xml&#39;&quot;</span>&lt;&lt;std::endl;</div><div class="line"> std::cout&lt;&lt;<span class="stringliteral">&quot; =&gt; you can use this to fine tune parameters and load them if you save to file &#39;RetinaSpecificParameters.xml&#39;&quot;</span>&lt;&lt;std::endl;</div><div class="line">}</div></div><!-- fragment --><p> Then, start the main program and first declare a <em><a class="el" href="../../d3/d63/classcv_1_1Mat.html" title="n-dimensional dense array class ">cv::Mat</a></em> matrix in which input images will be loaded. Also allocate a <em><a class="el" href="../../d8/dfe/classcv_1_1VideoCapture.html" title="Class for video capturing from video files, image sequences or cameras. ">cv::VideoCapture</a></em> object ready to load video streams (if necessary) </p><div class="fragment"><div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span>* argv[]) {</div><div class="line">  <span class="comment">// declare the retina input buffer... that will be fed differently in regard of the input media</span></div><div class="line">  <a class="code" href="../../d3/d63/classcv_1_1Mat.html">cv::Mat</a> inputFrame;</div><div class="line">  <a class="code" href="../../d8/dfe/classcv_1_1VideoCapture.html">cv::VideoCapture</a> videoCapture; <span class="comment">// in case a video media is used, its manager is declared here</span></div></div><!-- fragment --><p> In the main program, before processing, first check input command parameters. Here it loads a first input image coming from a single loaded image (if user chose command <em>-image</em>) or from a video stream (if user chose command <em>-video</em>). Also, if the user added <em>log</em> command at the end of its program call, the spatial logarithmic image sampling performed by the retina is taken into account by the Boolean flag <em>useLogSampling</em>. </p><div class="fragment"><div class="line"><span class="comment">// welcome message</span></div><div class="line">  std::cout&lt;&lt;<span class="stringliteral">&quot;****************************************************&quot;</span>&lt;&lt;std::endl;</div><div class="line">  std::cout&lt;&lt;<span class="stringliteral">&quot;* Retina demonstration : demonstrates the use of is a wrapper class of the Gipsa/Listic Labs retina model.&quot;</span>&lt;&lt;std::endl;</div><div class="line">  std::cout&lt;&lt;<span class="stringliteral">&quot;* This demo will try to load the file &#39;RetinaSpecificParameters.xml&#39; (if exists).\nTo create it, copy the autogenerated template &#39;RetinaDefaultParameters.xml&#39;.\nThen tweak it with your own retina parameters.&quot;</span>&lt;&lt;std::endl;</div><div class="line">  <span class="comment">// basic input arguments checking</span></div><div class="line">  <span class="keywordflow">if</span> (argc&lt;2)</div><div class="line">  {</div><div class="line">      help(<span class="stringliteral">&quot;bad number of parameter&quot;</span>);</div><div class="line">      <span class="keywordflow">return</span> -1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">bool</span> useLogSampling = !strcmp(argv[argc-1], <span class="stringliteral">&quot;log&quot;</span>); <span class="comment">// check if user wants retina log sampling processing</span></div><div class="line"></div><div class="line">  std::string inputMediaType=argv[1];</div><div class="line"></div><div class="line">  <span class="comment">// checking input media type (still image, video file, live video acquisition)</span></div><div class="line">  <span class="keywordflow">if</span> (!strcmp(inputMediaType.c_str(), <span class="stringliteral">&quot;-image&quot;</span>) &amp;&amp; argc &gt;= 3)</div><div class="line">  {</div><div class="line">      std::cout&lt;&lt;<span class="stringliteral">&quot;RetinaDemo: processing image &quot;</span>&lt;&lt;argv[2]&lt;&lt;std::endl;</div><div class="line">      <span class="comment">// image processing case</span></div><div class="line">      inputFrame = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv::imread</a>(std::string(argv[2]), 1); <span class="comment">// load image in RGB mode</span></div><div class="line">  }<span class="keywordflow">else</span></div><div class="line">      <span class="keywordflow">if</span> (!strcmp(inputMediaType.c_str(), <span class="stringliteral">&quot;-video&quot;</span>))</div><div class="line">      {</div><div class="line">          <span class="keywordflow">if</span> (argc == 2 || (argc == 3 &amp;&amp; useLogSampling)) <span class="comment">// attempt to grab images from a video capture device</span></div><div class="line">          {</div><div class="line">              videoCapture.<a class="code" href="../../d8/dfe/classcv_1_1VideoCapture.html#a614a1702e15f42ede5100014ce7f48ed">open</a>(0);</div><div class="line">          }<span class="keywordflow">else</span><span class="comment">// attempt to grab images from a video filestream</span></div><div class="line">          {</div><div class="line">              std::cout&lt;&lt;<span class="stringliteral">&quot;RetinaDemo: processing video stream &quot;</span>&lt;&lt;argv[2]&lt;&lt;std::endl;</div><div class="line">              videoCapture.<a class="code" href="../../d8/dfe/classcv_1_1VideoCapture.html#a614a1702e15f42ede5100014ce7f48ed">open</a>(argv[2]);</div><div class="line">          }</div><div class="line"></div><div class="line">          <span class="comment">// grab a first frame to check if everything is ok</span></div><div class="line">          videoCapture&gt;&gt;inputFrame;</div><div class="line">      }<span class="keywordflow">else</span></div><div class="line">      {</div><div class="line">          <span class="comment">// bad command parameter</span></div><div class="line">          help(<span class="stringliteral">&quot;bad command parameter&quot;</span>);</div><div class="line">          <span class="keywordflow">return</span> -1;</div><div class="line">      }</div></div><!-- fragment --><p> Once all input parameters are processed, a first image should have been loaded, if not, display error and stop program : </p><div class="fragment"><div class="line"><span class="keywordflow">if</span> (inputFrame.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abbec3525a852e77998aba034813fded4">empty</a>())</div><div class="line">{</div><div class="line">    help(<span class="stringliteral">&quot;Input media could not be loaded, aborting&quot;</span>);</div><div class="line">    <span class="keywordflow">return</span> -1;</div><div class="line">}</div></div><!-- fragment --><p> Now, everything is ready to run the retina model. I propose here to allocate a retina instance and to manage the eventual log sampling option. The Retina constructor expects at least a <a class="el" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">cv::Size</a> object that shows the input data size that will have to be managed. One can activate other options such as color and its related color multiplexing strategy (here Bayer multiplexing is chosen using <em>enum <a class="el" href="../../dd/deb/group__bioinspired.html#gga9960117097f8d8ba20bafa0098ea20d1aaadeb7c2a3a68e14d700f15ed4323b62" title="standard bayer sampling ">cv::bioinspired::RETINA_COLOR_BAYER</a></em>). If using log sampling, the image reduction factor (smaller output images) and log sampling strength can be adjusted. </p><div class="fragment"><div class="line"><span class="comment">// pointer to a retina object</span></div><div class="line"><a class="code" href="../../dc/d84/group__core__basic.html#ga6395ca871a678020c4a31fadf7e8cc63">cv::Ptr&lt;cv::bioinspired::Retina&gt;</a> myRetina;</div><div class="line"></div><div class="line"><span class="comment">// if the last parameter is &#39;log&#39;, then activate log sampling (favour foveal vision and subsamples peripheral vision)</span></div><div class="line"><span class="keywordflow">if</span> (useLogSampling)</div><div class="line">{</div><div class="line">    myRetina = cv::bioinspired::createRetina(inputFrame.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a146f8e8dda07d1365a575ab83d9828d1">size</a>(), <span class="keyword">true</span>, <a class="code" href="../../dd/deb/group__bioinspired.html#gga9960117097f8d8ba20bafa0098ea20d1aaadeb7c2a3a68e14d700f15ed4323b62">cv::bioinspired::RETINA_COLOR_BAYER</a>, <span class="keyword">true</span>, 2.0, 10.0);</div><div class="line">}</div><div class="line"><span class="keywordflow">else</span><span class="comment">// -&gt; else allocate &quot;classical&quot; retina :</span></div><div class="line">    myRetina = cv::bioinspired::createRetina(inputFrame.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a146f8e8dda07d1365a575ab83d9828d1">size</a>());</div></div><!-- fragment --><p> Once done, the proposed code writes a default xml file that contains the default parameters of the retina. This is useful to make your own config using this template. Here generated template xml file is called <em>RetinaDefaultParameters.xml</em>. </p><div class="fragment"><div class="line"><span class="comment">// save default retina parameters file in order to let you see this and maybe modify it and reload using method &quot;setup&quot;</span></div><div class="line">myRetina-&gt;write(<span class="stringliteral">&quot;RetinaDefaultParameters.xml&quot;</span>);</div></div><!-- fragment --><p> In the following line, the retina attempts to load another xml file called <em>RetinaSpecificParameters.xml</em>. If you created it and introduced your own setup, it will be loaded, in the other case, default retina parameters are used. </p><div class="fragment"><div class="line"><span class="comment">// load parameters if file exists</span></div><div class="line">myRetina-&gt;setup(<span class="stringliteral">&quot;RetinaSpecificParameters.xml&quot;</span>);</div></div><!-- fragment --><p> It is not required here but just to show it is possible, you can reset the retina buffers to zero to force it to forget past events. </p><div class="fragment"><div class="line"><span class="comment">// reset all retina buffers (imagine you close your eyes for a long time)</span></div><div class="line">myRetina-&gt;clearBuffers();</div></div><!-- fragment --><p> Now, it is time to run the retina ! First create some output buffers ready to receive the two retina channels outputs </p><div class="fragment"><div class="line"><span class="comment">// declare retina output buffers</span></div><div class="line"><a class="code" href="../../d3/d63/classcv_1_1Mat.html">cv::Mat</a> retinaOutput_parvo;</div><div class="line"><a class="code" href="../../d3/d63/classcv_1_1Mat.html">cv::Mat</a> retinaOutput_magno;</div></div><!-- fragment --><p> Then, run retina in a loop, load new frames from video sequence if necessary and get retina outputs back to dedicated buffers. </p><div class="fragment"><div class="line"><span class="comment">// processing loop with no stop condition</span></div><div class="line"><span class="keywordflow">while</span>(<span class="keyword">true</span>)</div><div class="line">{</div><div class="line">    <span class="comment">// if using video stream, then, grabbing a new frame, else, input remains the same</span></div><div class="line">    <span class="keywordflow">if</span> (videoCapture.<a class="code" href="../../d8/dfe/classcv_1_1VideoCapture.html#a9d2ca36789e7fcfe7a7be3b328038585">isOpened</a>())</div><div class="line">        videoCapture&gt;&gt;inputFrame;</div><div class="line"></div><div class="line">    <span class="comment">// run retina filter on the loaded input frame</span></div><div class="line">    myRetina-&gt;run(inputFrame);</div><div class="line">    <span class="comment">// Retrieve and display retina output</span></div><div class="line">    myRetina-&gt;getParvo(retinaOutput_parvo);</div><div class="line">    myRetina-&gt;getMagno(retinaOutput_magno);</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">cv::imshow</a>(<span class="stringliteral">&quot;retina input&quot;</span>, inputFrame);</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">cv::imshow</a>(<span class="stringliteral">&quot;Retina Parvo&quot;</span>, retinaOutput_parvo);</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">cv::imshow</a>(<span class="stringliteral">&quot;Retina Magno&quot;</span>, retinaOutput_magno);</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">cv::waitKey</a>(10);</div><div class="line">}</div></div><!-- fragment --><p> That's done ! But if you want to secure the system, take care and manage Exceptions. The retina can throw some when it sees irrelevant data (no input frame, wrong setup, etc.). Then, i recommend to surround all the retina code by a try/catch system like this : </p><div class="fragment"><div class="line"><span class="keywordflow">try</span>{</div><div class="line">     <span class="comment">// pointer to a retina object</span></div><div class="line">     <a class="code" href="../../dc/d84/group__core__basic.html#ga6395ca871a678020c4a31fadf7e8cc63">cv::Ptr&lt;cv::Retina&gt;</a> myRetina;</div><div class="line">     [---]</div><div class="line">     <span class="comment">// processing loop with no stop condition</span></div><div class="line">     <span class="keywordflow">while</span>(<span class="keyword">true</span>)</div><div class="line">     {</div><div class="line">         [---]</div><div class="line">     }</div><div class="line"></div><div class="line">}<span class="keywordflow">catch</span>(<a class="code" href="../../d1/dee/classcv_1_1Exception.html">cv::Exception</a> e)</div><div class="line">{</div><div class="line">    std::cerr&lt;&lt;<span class="stringliteral">&quot;Error using Retina : &quot;</span>&lt;&lt;e.<a class="code" href="../../d1/dee/classcv_1_1Exception.html#a9c1e692401016807255e0e6ad562ece9">what</a>()&lt;&lt;std::endl;</div><div class="line">}</div></div><!-- fragment --><h2>Retina parameters, what to do ? </h2>
<p>First, it is recommended to read the reference paper <a class="el" href="../../d0/de3/citelist.html#CITEREF_Benoit2010">[19]</a></p>
<p>Once done open the configuration file <em>RetinaDefaultParameters.xml</em> generated by the demo and let's have a look at it. </p><div class="fragment"><div class="line">&lt;?xml version=<span class="stringliteral">&quot;1.0&quot;</span>?&gt;</div><div class="line">&lt;opencv_storage&gt;</div><div class="line">&lt;OPLandIPLparvo&gt;</div><div class="line">    &lt;colorMode&gt;1&lt;/colorMode&gt;</div><div class="line">    &lt;normaliseOutput&gt;1&lt;/normaliseOutput&gt;</div><div class="line">    &lt;photoreceptorsLocalAdaptationSensitivity&gt;7.5e-01&lt;/photoreceptorsLocalAdaptationSensitivity&gt;</div><div class="line">    &lt;photoreceptorsTemporalConstant&gt;9.0e-01&lt;/photoreceptorsTemporalConstant&gt;</div><div class="line">    &lt;photoreceptorsSpatialConstant&gt;5.7e-01&lt;/photoreceptorsSpatialConstant&gt;</div><div class="line">    &lt;horizontalCellsGain&gt;0.01&lt;/horizontalCellsGain&gt;</div><div class="line">    &lt;hcellsTemporalConstant&gt;0.5&lt;/hcellsTemporalConstant&gt;</div><div class="line">    &lt;hcellsSpatialConstant&gt;7.&lt;/hcellsSpatialConstant&gt;</div><div class="line">    &lt;ganglionCellsSensitivity&gt;7.5e-01&lt;/ganglionCellsSensitivity&gt;&lt;/OPLandIPLparvo&gt;</div><div class="line">&lt;IPLmagno&gt;</div><div class="line">    &lt;normaliseOutput&gt;1&lt;/normaliseOutput&gt;</div><div class="line">    &lt;parasolCells_beta&gt;0.&lt;/parasolCells_beta&gt;</div><div class="line">    &lt;parasolCells_tau&gt;0.&lt;/parasolCells_tau&gt;</div><div class="line">    &lt;parasolCells_k&gt;7.&lt;/parasolCells_k&gt;</div><div class="line">    &lt;amacrinCellsTemporalCutFrequency&gt;2.0e+00&lt;/amacrinCellsTemporalCutFrequency&gt;</div><div class="line">    &lt;V0CompressionParameter&gt;9.5e-01&lt;/V0CompressionParameter&gt;</div><div class="line">    &lt;localAdaptintegration_tau&gt;0.&lt;/localAdaptintegration_tau&gt;</div><div class="line">    &lt;localAdaptintegration_k&gt;7.&lt;/localAdaptintegration_k&gt;&lt;/IPLmagno&gt;</div><div class="line">&lt;/opencv_storage&gt;</div></div><!-- fragment --><p> Here are some hints but actually, the best parameter setup depends more on what you want to do with the retina rather than the images input that you give to retina. Apart from the more specific case of High Dynamic Range images (HDR) that require more specific setup for specific luminance compression objective, the retina behaviors should be rather stable from content to content. Note that OpenCV is able to manage such HDR format thanks to the OpenEXR images compatibility.</p>
<p>Then, if the application target requires details enhancement prior to specific image processing, you need to know if mean luminance information is required or not. If not, the the retina can cancel or significantly reduce its energy thus giving more visibility to higher spatial frequency details.</p>
<h4>Basic parameters</h4>
<p>The simplest parameters are as follows :</p>
<ul>
<li><b>colorMode</b> : let the retina process color information (if 1) or gray scale images (if 0). In that last case, only the first channels of the input will be processed.</li>
<li><b>normaliseOutput</b> : each channel has such parameter: if the value is set to 1, then the considered channel's output is rescaled between 0 and 255. Be aware at this case of the Magnocellular output level (motion/transient channel detection). Residual noise will also be rescaled !</li>
</ul>
<p><b>Note :</b> using color requires color channels multiplexing/demultipexing which also demands more processing. You can expect much faster processing using gray levels : it would require around 30 product per pixel for all of the retina processes and it has recently been parallelized for multicore architectures.</p>
<h4>Photo-receptors parameters</h4>
<p>The following parameters act on the entry point of the retina - photo-receptors - and has impact on all of the following processes. These sensors are low pass spatio-temporal filters that smooth temporal and spatial data and also adjust their sensitivity to local luminance,thus, leads to improving details extraction and high frequency noise canceling.</p>
<ul>
<li><b>photoreceptorsLocalAdaptationSensitivity</b> between 0 and 1. Values close to 1 allow high luminance log compression's effect at the photo-receptors level. Values closer to 0 provide a more linear sensitivity. Increased alone, it can burn the <em>Parvo (details channel)</em> output image. If adjusted in collaboration with <b>ganglionCellsSensitivity</b>,images can be very contrasted whatever the local luminance there is... at the cost of a naturalness decrease.</li>
<li><b>photoreceptorsTemporalConstant</b> this setups the temporal constant of the low pass filter effect at the entry of the retina. High value leads to strong temporal smoothing effect : moving objects are blurred and can disappear while static object are favored. But when starting the retina processing, stable state is reached later.</li>
<li><b>photoreceptorsSpatialConstant</b> specifies the spatial constant related to photo-receptors' low pass filter's effect. Those parameters specify the minimum value of the spatial signal period allowed in what follows. Typically, this filter should cut high frequency noise. On the other hand, a 0 value cuts none of the noise while higher values start to cut high spatial frequencies, and progressively lower frequencies... Be aware to not go to high levels if you want to see some details of the input images ! A good compromise for color images is a 0.53 value since such choice won't affect too much the color spectrum. Higher values would lead to gray and blurred output images.</li>
</ul>
<h4>Horizontal cells parameters</h4>
<p>This parameter set tunes the neural network connected to the photo-receptors, the horizontal cells. It modulates photo-receptors sensitivity and completes the processing for final spectral whitening (part of the spatial band pass effect thus favoring visual details enhancement).</p>
<ul>
<li><b>horizontalCellsGain</b> here is a critical parameter ! If you are not interested with the mean luminance and want just to focus on details enhancement, then, set this parameterto zero. However, if you want to keep some environment luminance's data, let some low spatial frequencies pass into the system and set a higher value (&lt;1).</li>
<li><b>hcellsTemporalConstant</b> similar to photo-receptors, this parameter acts on the temporal constant of a low pass temporal filter that smoothes input data. Here, a high value generates a high retina after effect while a lower value makes the retina more reactive. This value should be lower than <b>photoreceptorsTemporalConstant</b> to limit strong retina after effects.</li>
<li><b>hcellsSpatialConstant</b> is the spatial constant of these cells filter's low pass one. It specifies the lowest spatial frequency allowed in what follows. Visually, a high value leads to very low spatial frequencies processing and leads to salient halo effects. Lower values reduce this effect but has the limit of not go lower than the value of <b>photoreceptorsSpatialConstant</b>. Those 2 parameters actually specify the spatial band-pass of the retina.</li>
</ul>
<p><b>NOTE</b> Once the processing managed by the previous parameters is done, input data is cleaned from noise and luminance is already partly enhanced. The following parameters act on the last processing stages of the two outing retina signals.</p>
<h4>Parvo (details channel) dedicated parameter</h4>
<ul>
<li><b>ganglionCellsSensitivity</b> specifies the strength of the final local adaptation occurring at the output of this details' dedicated channel. Parameter values remain between 0 and 1. Low value tend to give a linear response while higher values enforce the remaining low contrasted areas.</li>
</ul>
<p><b>Note :</b> this parameter can correct eventual burned images by favoring low energetic details of the visual scene, even in bright areas.</p>
<h4>IPL Magno (motion/transient channel) parameters</h4>
<p>Once image's information are cleaned, this channel acts as a high pass temporal filter that selects only the signals related to transient signals (events, motion, etc.). A low pass spatial filter smoothes extracted transient data while a final logarithmic compression enhances low transient events thus enhancing event sensitivity.</p>
<ul>
<li><b>parasolCells_beta</b> generally set to zero, can be considered as an amplifier gain at the entry point of this processing stage. Generally set to 0.</li>
<li><b>parasolCells_tau</b> the temporal smoothing effect that can be added</li>
<li><b>parasolCells_k</b> the spatial constant of the spatial filtering effect, set it at a high value to favor low spatial frequency signals that are lower subject for residual noise.</li>
<li><b>amacrinCellsTemporalCutFrequency</b> specifies the temporal constant of the high pass filter. High values let slow transient events to be selected.</li>
<li><b>V0CompressionParameter</b> specifies the strength of the log compression. Similar behaviors to previous description but here enforces sensitivity of transient events.</li>
<li><b>localAdaptintegration_tau</b> generally set to 0, has no real use actually in here.</li>
<li><b>localAdaptintegration_k</b> specifies the size of the area on which local adaptation is performed. Low values lead to short range local adaptation (higher sensitivity to noise), high values secure log compression. </li>
</ul>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:38 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
